<?php
//获取IP
if(!function_exists('GetIP'))
{
    function GetIP()
    {
        static $ip = NULL;
        if($ip !== NULL) return $ip;

        if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos = array_search('unknown',$arr);
            if(false !== $pos) unset($arr[$pos]);
            $ip  = trim($arr[0]);
        }
        else if(isset($_SERVER['HTTP_CLIENT_IP']))
        {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        }
        else if(isset($_SERVER['REMOTE_ADDR']))
        {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        //IP地址合法验证
        $ip = (false !== ip2long($ip)) ? $ip : '0.0.0.0';
        return $ip;
    }
}
/*文件根目录*/
//print_r(preg_replace("/[\/\\\\]{1,}/", '/', substr(dirname(__FILE__),0,-8)));die;
define('ROOTXY',preg_replace("/[\/\\\\]{1,}/", '/', substr(dirname(__FILE__),0,-8)));
class weixinxcx
{
	public $timeout = 30;
    public $connecttimeout = 30;
    public $http_code;
    public $debug = false;
    private $appID = '';
    private $appsecret = '';
    public $http_info = '';
    private $appid = '';//支付商户商户账号appid
    private $mchid = '';//商户号
    private $xcxpaykey = '';//支付秘钥
    private $sslcert_path = 'yr.pem';//证书pem路径
    private $sslkey_path = 'yrcertey.pem';//证书密钥pem路径
    /*登录凭证校验*/
    public function getUserSessionKey($js_code='')
    {
        $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$this->appID.'&secret='.$this->appsecret.'&js_code='.$js_code.'&grant_type=authorization_code';
        $res = $this->http($url);
        $res = json_decode($res,true);
        return $res;
    }
    /**
     *  作用：产生随机字符串，不长于32位
     */
    public function createNoncestr($length=16) 
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
        $str ="";
        for($i = 0;$i<$length;$i++ )
        {  
            $str.= substr($chars,mt_rand(0,strlen($chars)-1),1); 
        }
        return $str;
    }
    /*生成xml*/
    public function creatXml($arr=array(),$type=0)
    {
        $xml = '<xml>';
        foreach ($arr as $key => $value) 
        {
            if($type > 0)
            {
                $xml .= '<'.$key.'><![CDATA['.$value.']]></'.$key.'>';
            }
            else
            {
                $xml .= '<'.$key.'>'.$value.'</'.$key.'>';
            }
        }
        $xml .= '</xml>';
        return $xml;
    }
    /*xml转化array*/
    public function xmlToArray($xml)
    {
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array_data;
    }
    /*企业向小程序付款*/
    public function payToXcx($arr=array())
    {
        /*商户账号appid*/
        $data['mch_appid'] = $this->appid;
        /*商户号*/
        $data['mchid'] = $this->mchid;
        /*随机字符串*/
        $data['nonce_str'] = $this->createNoncestr();
        /*商户订单号*/
        $data['partner_trade_no'] = isset($arr['order_sn']) ? trim($arr['order_sn']) : '';
        /*用户openid*/
        $data['openid'] = isset($arr['openid']) ? trim($arr['openid']) : '';
        /*校验用户姓名选项*/
        $data['check_name'] = 'NO_CHECK';
        /*金额*/
        $data['amount'] = isset($arr['money']) ? $arr['money']*100 : 0;
        /*企业付款备注*/
        $data['desc'] = isset($arr['desc']) ? trim($arr['desc']) : '活动';
        /*Ip地址*/
        $data['spbill_create_ip'] = GetIP();
        /*签名*/
        $data['sign'] = $this->createSign($data);
        /*xml*/
        $xml = $this->creatXml($data);
        //print_r(ROOTXY.$this->sslcert_path);
        //print_r($xml);die;
        /*支付地址*/
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
        $res = $this->httpSslPost($url,$xml);
        /*$xml = '<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[参数错误：输入的商户订单号有误]]></return_msg>
<result_code><![CDATA[FAIL]]></result_code>
<err_code><![CDATA[PARAM_ERROR]]></err_code>
<err_code_des><![CDATA[参数错误：输入的商户订单号有误]]></err_code_des>
</xml>';*/
        $res = $this->xmlToArray($res);
        //print_r($res);
        return $res;
    }
    /*查询是否支付成功*/
    public function queryOrder($arr=array())
    {
        /*商户账号appid*/
        $data['appid'] = $this->appid;
        /*商户号*/
        $data['mch_id'] = $this->mchid;
        /*随机字符串*/
        $data['nonce_str'] = $this->createNoncestr();
        /*商户订单号*/
        $data['partner_trade_no'] = isset($arr['order_sn']) ? trim($arr['order_sn']) : '';
        /*签名*/
        $post['sign'] = $this->createSign($data);
        $post['partner_trade_no'] = $data['partner_trade_no'];
        $post['mch_id'] = $data['mch_id'];
        $post['appid'] = $data['appid'];
        $post['nonce_str'] = $data['nonce_str'];
        /*xml*/
        $xml = $this->creatXml($post,1);
        /*企业查询地址*/
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo';
        $res = $this->httpSslPost($url,$xml);
        $res = $this->xmlToArray($res);
        return $res;
    }
    /*格式化签名*/
    private function signFormat($arr=array())
    {
        $buff = '';
        foreach ($arr as $key => $value) 
        {
            if(!empty($value))
            {
                $buff .= $key.'='.$value.'&';
            }
        }
        return $buff;
    }
    /*生成签名*/
    private function createSign($arr=array())
    {
        //签名步骤一：按字典序排序参数
        ksort($arr);
        /*第二步，在stringA最后拼接上key得到stringSignTemp字符串，并对stringSignTemp进行MD5运算，再将得到的字符串所有字符转换为大写，得到sign值signValue。*/
        $str = $this->signFormat($arr);
        $str .= 'key='.$this->xcxpaykey;
        /*MD5签名方式*/
        $str = md5($str);
        //签名步骤四：所有字符转为大写
        $result_ = strtoupper($str);
        return $result_;
    }
    /*带ssl验证的post*/
    public function httpSslPost($url,$postfields = NULL,$headers = array())
    {
        //print_r($url);die;
        /*创建一个新cURL资源*/
        $curl = curl_init();
        /*在尝试连接时等待的秒数。设置为0，则无限等待*/
        curl_setopt($curl,CURLOPT_CONNECTTIMEOUT,$this->connecttimeout);
        /*允许 cURL 函数执行的最长秒数。*/
        curl_setopt($curl,CURLOPT_TIMEOUT,$this->timeout);
        /* 将curl_exec()获取的信息以字符串返回，而不是直接输出。*/
        curl_setopt($curl,CURLOPT_RETURNTRANSFER,TRUE);
        /*判断请求是否是https*/
        if(stripos($url,'https://') !== false)
        {
            /*禁止cURL验证对等证书*/
            curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
            /*解决兼容  值 1 的支持在 cURL 7.28.1 中被删除了。*/
            curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);
        }
        //使用证书：cert 与 key 分别属于两个.pem文件
        //默认格式为PEM，可以注释
        curl_setopt($curl,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($curl,CURLOPT_SSLCERT,ROOTXY.$this->sslcert_path);
        //默认格式为PEM，可以注释
        curl_setopt($curl,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($curl,CURLOPT_SSLKEY,ROOTXY.$this->sslkey_path);
        /*TRUE 时会发送 POST 请求，类型为：application/x-www-form-urlencoded，是 HTML 表单提交时最常见的一种。*/
        curl_setopt($curl, CURLOPT_POST, TRUE);
        curl_setopt($curl,CURLOPT_POSTFIELDS,$postfields);
        /*请求的url配置*/
        curl_setopt($curl,CURLOPT_URL,$url);
        /*设置 HTTP 头字段的数组。*/
        curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);
        /*执行资源*/
        $res = curl_exec($curl);
        /*返回码*/
        $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        /*关闭cURL资源，并且释放系统资源*/
        curl_close($curl);
        if($http_code == 200)
        {
            return $res;
        }
        else
        {
            return false;
        }
    }
	/**
     * Make an HTTP request
     *
     * @return string API results
     * @ignore
     */
    public function http($url, $method='GET', $postfields = NULL, $headers = array()) 
    {
    	$this->http_info = array();
        $ci = curl_init();
        /* Curl settings */
        curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
        curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
        curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ci, CURLOPT_ENCODING, "");
        curl_setopt($ci, CURLOPT_HEADER, FALSE);
        switch ($method) {
            case 'POST':
                curl_setopt($ci, CURLOPT_POST, TRUE);
                if (!empty($postfields)) {
                    curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
                }
                break;
        }
        curl_setopt($ci, CURLOPT_URL, $url);
        curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE);
        if(stripos($url,"https://")!==FALSE)
        {
            curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, false);
        }
        $response = curl_exec($ci);
        $this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
        $this->http_info = array_merge($this->http_info, curl_getinfo($ci));
        if ($this->debug) {
            echo "=====post data======\r\n";
            var_dump($postfields);
            echo "=====headers======\r\n";
            print_r($headers);
            echo '=====request info=====' . "\r\n";
            print_r(curl_getinfo($ci));
            echo '=====response=====' . "\r\n";
            print_r($response);
        }
        curl_close($ci);
        return $response;
    }
}